
package lipengfei.botaiframework.jwt;

import java.util.Date;

import com.auth0.jwt.exceptions.TokenExpiredException;
import org.springframework.stereotype.Component;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

//@Slf4j
@Component
public class JwtUtil {


    /**
     * 根据 account和当前时间生成JWTToken
     */
    public static String generateToken(JwtProperties jwtProperties, String account, Date currentTime) {
        try {
            if (StrUtil.isBlank(account)) {
                return null;
            }

            Date expireDate = new Date(currentTime.getTime() + jwtProperties.getExpire() * 1000);
            String token = JWT.create().withClaim(JwtConst.ACCOUNT, account)
                    // jwt唯一id
                    .withJWTId(IdUtil.randomUUID())
                    // 签发人
                    .withIssuer(jwtProperties.getIssuer())
                    // 主题
                    .withSubject(jwtProperties.getSubject())
                    // 签发的目标
                    .withAudience(jwtProperties.getAudience())
                    // 签名时间
                    .withIssuedAt(currentTime)
                    // token过期时间
                    .withExpiresAt(expireDate)
                    // 签名
                    .sign(Algorithm.HMAC256(jwtProperties.getSecret()));

            return token;
        } catch (Exception e) {
            //log.error("generateToken exception", e);
        }
        return null;
    }

    /**
     * 验证JWTtoken 同时验证签发人、签发主题、签发目标。
     */
    public static boolean verify(JwtProperties jwtProperties, String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(jwtProperties.getSecret());
            JWTVerifier verifier = JWT.require(algorithm)
                    // 签发人
                    .withIssuer(jwtProperties.getIssuer())
                    // 签发主题
                    .withSubject(jwtProperties.getSubject())
                    // 签发目标
                    .withAudience(jwtProperties.getAudience())

                    .build();

            DecodedJWT jwt = verifier.verify(token);
            if (jwt != null) {
                return true;
            }
        } catch (Exception e) {

            //log.error("Verify jwt  Exception", e);
        }
        return false;
    }


	/**
	 * 验证JWTtoken 同时验证签发人、签发主题、签发目标。
	 */
	public static boolean verifyIgnoreExpiresAt(JwtProperties jwtProperties, String token) {
		try {
			Algorithm algorithm = Algorithm.HMAC256(jwtProperties.getSecret());
			JWTVerifier verifier = JWT.require(algorithm)
					// 签发人
					.withIssuer(jwtProperties.getIssuer())
					// 签发主题
					.withSubject(jwtProperties.getSubject())
					// 签发目标
					.withAudience(jwtProperties.getAudience())

					.build();

			DecodedJWT jwt = verifier.verify(token);
			if (jwt != null) {
				return true;
			}
		} catch (Exception e) {
			if(e instanceof TokenExpiredException){
				return true;
			}
			//log.error("Verify jwt  Exception", e);
		}
		return false;
	}

	/**
     * 获得Token中的withClaim信息，无需secret解密也能获得。
     */
    public static String getClaim(String token, String claimKey) {
        if (StrUtil.isBlank(token)) {
            return null;
        }
        DecodedJWT decodedJwt = JWT.decode(token);
        if (decodedJwt == null) {
            return null;
        }
        String claimValue = decodedJwt.getClaim(claimKey).asString();
        return claimValue;
    }

    /**
     * 获取发行人Issuer，无需secret解密也能获得。
     */
    public static Date getIssuedAt(String token) {
        DecodedJWT decodedJwt = JWT.decode(token);
        if (decodedJwt == null) {
            return null;
        }
        return decodedJwt.getIssuedAt();
    }

    /**
     * 获取过期时间expiresAt，无需secret解密也能获得。
     **/
    public static Date getExpireDate(String token) {
        DecodedJWT decodedJwt = JWT.decode(token);
        if (decodedJwt == null) {
            return null;
        }
        return decodedJwt.getExpiresAt();
    }

    /***
     * 判断token是否已过期
     *
     */
    public static boolean isExpired(String token) {
        Date expireDate = getExpireDate(token);
        if (expireDate == null) {
            return true;
        }
        return expireDate.before(new Date());
    }

    public static void main(String[] args) {
		JwtProperties jwtProperties = new JwtProperties();
		jwtProperties.setExpire(5L);
       // System.out.println(JwtUtil.generateToken(jwtProperties,"qqqq",new Date()));
		boolean b= JwtUtil.verifyIgnoreExpiresAt(jwtProperties,"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ3ZWIiLCJhdWQiOiJjbGllbnQiLCJpc3MiOiJzZXJ2ZXIiLCJleHAiOjE2NTIzMjAwMTgsImlhdCI6MTY1MjMyMDAxMywiYWNjb3VudCI6InFxcXEiLCJqdGkiOiIyM2Q2ZjU4My03YzE3LTQ2NmYtOTIxMC1jN2E3ZjUzN2IyNjcifQ.bhVZKWB8q9LeYsYXQ_90UxQSCaLL84GQqfDC_d7AgjQ");
		System.out.println(b);
    }
}
